home *** CD-ROM | disk | FTP | other *** search
- {$X+,B-,V-} {essential compiler directives}
-
- UNIT nwLock;
-
- { nwLock unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk
-
- This unit was based on units by
-
- a. Scott A. Lewis, 36 Maythorpe Drive, Windsor, CT 06095, U.S.A.
- Note: (1987) 76515,135@Compuserve.Com
-
- b. Erik van Heyningen, Hague Consulting Group,
- The Hague, the Netherlands.
- Note: (1994) hcg@hacktick.nl }
-
- { Function: Interrupt: Notes:
-
- Physical File locking/unlocking
- -------------------------------
-
- * LogPhysicalFile EB (6) -> F203
- * LockPhysicalFileSet F204
- * ReleasePhysicalFile EC -> F205
- * ReleasePhysicalFileSet CD -> F206
- * ClearPhysicalFile ED (6) -> F207
- * ClearPhysicalFileSet CF -> F208
-
- Logical File Locking
- --------------------
-
- + LogLogicalFile (5)
- + LogLogicalFileSet (5)
- + ReleaseLogicalFile (5)
- + ReleaseLogicalFileSet (5)
- + ClearLogicalFile (5)
- + ClearLogicalFileSet (5)
-
- Logical record locking/unlocking
- --------------------------------
-
- * LogLogicalRecord D0 -> F209
- * LockLogicalRecordSet D1 -> F20A
- * ReleaseLogicalRecord D2 -> F20C
- * ReleaseLogicalRecordSet D3 -> F20D
- * ClearLogicalRecord D4 -> F20B
- * ClearLogicalRecordSet D5 -> F20E
-
- GetLogicalRecordInformation F217/F0 (3)
- GetLogicalRecordsByConnection F217/EF (3)
-
- Physical record locking/unlocking
- ---------------------------------
-
- . LogPhysicalRecord BC -> F21A
- . LockPhysicalRecordSet C2 -> F21B
- . ReleasePhysicalRecord BD -> F21C
- . ReleasePhysicalRecordSet C3 -> F21D
- . ClearPhysicalRecord BE -> F21E
- . ClearPhysicalRecordSet C4 -> F21F
-
- GetPhysRecLocksByConnectionAndFile F217/ED (3)
- GetPhysRecLocksByFile F217/EE (3)
-
- - ControlRecordAccess 5C (DOS) (4)
-
-
- Not Implemented
- ---------------
-
- - GetLockMode C600 (1)
- - SetLockMode C601 (1)
- - BeginLogicalFileLocking C8 / F201 (2)
- - EndLogicalFileLocking C9 / F202 (2)
-
- Notes: -Semaphores can be found in the nwSema Unit
- (1) Obsolete
- (2) Not supported by (all) 3.x versions
- (3) Supported by NW 3.x and upwards
- (4) Generic physical record locking call, DOS 3.1+
- Equivalent to:
- I . LockPhysicalRecord (without logging)
- II. ReleasePhysicalrecord
- (5) Use the equivalent LogicalRecordLocking calls
- to emulate LogicalFileLocking. NOTE: remember
- that there's only ONE Log.
- (6) Includes VLM fix for filenames (GetTrueEntryName
- in the nwFile unit is called)
- -> F2xx To be rewritten to the F2 interface.
- }
-
- INTERFACE
-
- Uses nwIntr,nwMisc;
-
- CONST { Log Resource }
- LD_LOG = 0;
- LD_LOG_LOCK = 1; { Deny all access to file/record }
- LD_LOG_LOCK_RO = 3; { Allow read / deny write (record locking only)}
- { Lock Resource }
- LD_lOCK = 0; { Deny all access to file/record }
- LD_LOCK_RO = 1; { Allow read / deny write (record locking only)}
-
- Var Result:word;
-
- {------------------- PHYSICAL FILE LOCKING OPERATIONS -----------------------}
-
- {F204 [2.15c+]}
- FUNCTION LockPhysicalFileSet(TimeoutLimit : Word) : Boolean;
- {Lock a set of files that were logged by the LogFile function }
-
- {CD.. [1.0+]}
- FUNCTION ReleasePhysicalFileSet:boolean;
- { Release lock on set of files in logged table, files remain logged }
-
- {CF [1.0+]}
- FUNCTION ClearPhysicalFileSet : Boolean;
- { Unlock and UnLog the entire logged file set }
-
- {EB.. [1.0+]}
- FUNCTION LogPhysicalFile(FileName : String; LockDirective : Byte; TimeoutLimit : Word) : Boolean;
- {Log files for later use }
-
- {EC.. [1.0+]}
- FUNCTION ReleasePhysicalFile(FileName : String) : boolean;
- {Release file lock, but keep logged in the table }
-
- {ED.. [1.0+]}
- FUNCTION ClearPhysicalFile(FileName : String) : boolean;
- {Release a file from the file log table, unlock the file if it is locked }
-
- { ------------------- LOGICAL RECORD LOCKING OPERATIONS --------------------}
-
- {D0 [1.0+]}
- FUNCTION LogLogicalRecord(Name:string; LockDirective:Byte; Timeout: Word) : Boolean;
- {Add a record to the lockable logical record table }
-
- {D1.. [1.0+]}
- FUNCTION LockLogicalRecordSet(LockDirective:Byte; TimeoutLimit : Word) : Boolean;
- {Lock all logged records }
-
- {D2.. [1.0+]}
- FUNCTION ReleaseLogicalRecord(Name : String) : Boolean;
- {Unlock a record, keep record in logtable }
-
- {D3.. [1.0+]}
- FUNCTION ReleaseLogicalRecordSet : Boolean;
- {Unlock all locked records, keep records logged }
-
- {D4.. [1.0+]}
- FUNCTION ClearLogicalRecord(Name : String) : Boolean;
- {Unlock and UnLog a record }
-
- {D5.. [1.0+]}
- FUNCTION ClearLogicalRecordSet : Boolean;
- {Unlocks and UnLogs all logged records }
-
- {F217/EF [2.1x+]}
- Function GetLogicalRecordLocksByConnection(ConnNbr:word;
- {i/o} Var NextRecNbr:word;
- Var TaskNbr:word;
- Var LockStatus:Byte;
- Var LockName:String):Boolean;
- { You need console operator rights to use this function }
-
-
- {----------------------- PHYSICAL RECORD LOCKING OPERATION -----------------}
-
- {BC.. [1.0+]}
- function LogPhysicalRecord(Handle:Word;
- LockDirective:Byte;
- RecordOffset,RecordLength:Longint;
- TimeOutLimit:Word): boolean;
- {Add a record to the lockable physical record logtable }
-
- {BD.. [1.0+]}
- function ReleasePhysicalRecord( Handle:Word; RecordOffset,RecordLength:Longint) : boolean;
- {Unlock record, keep record logged }
-
- {BE.. [1.0+]}
- function ClearPhysicalRecord(Handle:Word; RecordOffset,RecordLength:Longint): boolean;
- {Unlock and Unlog a record }
-
- {C2.. [1.0+]}
- function LockPhysicalRecordSet(LockDirective: byte; TimeoutLimit : Word): boolean;
- {Lock all logged records }
-
- {C3.. [1.0+]}
- function ReleasePhysicalRecordSet : boolean;
- {Unlock all logged records, keep records logged }
-
- {C4.. [1.0+]}
- function ClearPhysicalRecordSet : boolean;
- {Unlocks and unLogs all logged records }
-
-
- IMPLEMENTATION{==============================================================}
-
- uses nwFile;
-
- Var regs:TTRegisters;
-
-
- Procedure SetLockMode(mode:Byte);
- begin
- regs.AH:=$c6;
- regs.al:=mode; { 0 or 1 }
- RealModeIntr($21,regs);
- end;
-
- (* THE FOLLOWING PROCEDURES ARE FOR LOGGING AND LOCKING/RELEASING FILE SETS *)
- (* File locking by set can be very effective in avoiding deadly embrace *)
-
- {F204 [3.x+]}
- FUNCTION LockPhysicalFileSet(TimeoutLimit : Word) : Boolean;
- Type Treq=record
- _TimeOutLimit:Word;
- end;
- TPreq=^Treq;
- BEGIN
- With TPreq(GlobalReqBuf)^
- do begin
- _TimeoutLimit:=swap(TimeoutLimit);
- end;
- F2SystemCall($04,SizeOf(Treq),0,result);
- LockPhysicalFileSet:=(result=0);
- { 00 Successful FF Fail FE Timeout }
- END;
-
-
- {CD.. [1.0+]}
- FUNCTION ReleasePhysicalFileSet:boolean;
- { Release lock on set of files in logged table, files remain logged }
- { These files remain open but cannot be accessed without an error }
- { To reuse them, send another lock file set }
- Type Treq=record
- end;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $CD;
- RealModeIntr($21,Regs);
- result:=0;
- END;
- ReleasePhysicalFileSet:=true;
- END;
-
- {CF [2.0+]}
- FUNCTION ClearPhysicalFileSet : Boolean;
- { Unlock and UnLog the entire personal file set (all files are closed) }
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $CF;
- RealModeIntr($21,Regs);
- result:=0;
- END;
- ClearPhysicalFileSet:=true;
- END;
-
-
- {EB.. [2.0+] }
- FUNCTION LogPhysicalFile(FileName : String; LockDirective : Byte; TimeoutLimit : Word) : Boolean;
- { This function allows a station to log files for later personal use }
- { After the desired files are logged, function CBh can be used to lock }
- { the entire set of files }
- { !! There is a known problem with lock directive 3 (log and lock shareable)
- use 1 instead. }
- Type Treq=record
- LockDirective:Byte;
- TimeOutLimit:Word;
- FileName:string[255]; { or Asciiz ? }
- end;
- Var temp1,temp2:word;
- TEname:string;
- BEGIN
- GetTrueEntryName(FileName,TEname); { also UpCases string }
- { IF this function isn't included and VLMs are used, this call will
- *appear* to be successful. No error code is returned, the call is
- however unsuccessful. }
- WITH Regs
- DO BEGIN
- AH := $EB;
- AL := LockDirective; { 0 = Log Only, 1 Log and Lock }
- BP := TimeoutLimit; { in 1/18 seconds, 0 = No wait }
- TEname := TEName+#0; { Terminate with a nul for asciiz }
- Move(TEname[1],GlobalReqBuf^,ord(TEname[0]));
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- RealModeIntr($21,Regs);
- Result:=AL;
- LogPhysicalFile := (Result = 0);
- END;
- { FE Timeout FF hardware error }
- END;
-
-
- {EC.. [1.0+]}
- FUNCTION ReleasePhysicalFile(FileName : String) : boolean;
- { Release file lock, but keep logged in the table }
- Var temp1,temp2:word;
- TEname:string;
- BEGIN
- GetTrueEntryName(FileName,TEname); { also UpCases string }
- { IF this function isn't included and VLMs are used, this call will
- *appear* to be successful. No error code is returned, the call is
- however unsuccessful. }
- WITH Regs
- DO BEGIN
- AH := $EC;
- UpString(FileName);
- TEName := TEName+#0; { null terminate }
- Move(TEname[1],GlobalReqBuf^,ord(TEname[0]));
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- RealModeIntr($21,Regs);
- result:=AL;
- ReleasePhysicalFile:=(result=0);
- END;
- {FF File not found }
- END;
-
- {ED.. [1.0+]}
- FUNCTION ClearPhysicalFile(FileName : String) : boolean;
- { Release a file from the file log table, unlock the file if it is locked }
- Var temp1,temp2:word;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $ED;
- UpString(FileName);
- FileName := FileName+#0; { null terminate }
- Move(Filename[1],GlobalReqBuf^,ord(Filename[0]));
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- RealModeIntr($21,Regs);
- Result:=AL;
- ClearPhysicalFile := (Result = 0);
- { 0 means OK FF File not found}
- END;
- END;
-
-
- (* THE FOLLOWING FUNCTIONS ARE FOR LOGICAL LOCKING OPERATIONS *)
- (* Logical locks work only if all software accessing the files use the *)
- (* same logical synchronization scheme. Logical locks are much easier *)
- (* and faster to implement than physical locks. *)
-
-
- {D0 [1.0+]}
- FUNCTION LogLogicalRecord(Name:String; LockDirective:Byte; Timeout: Word) : Boolean;
- { This function will log the specified record string in the record log table }
- { of the requesting station. }
- { Max length of name: 99 chars }
- { LockDirective LD_LOG = 0;
- LD_LOG_LOCK = 1; Deny all access to file/record
- LD_LOG_LOCK_RO = 3; Allow read / deny write }
- { TimeOut=0 means NoWait }
- Var temp1,temp2:word;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D0;
- AL := LockDirective;
- UpString(Name);
- Move(Name,GlobalReqBuf^,ord(Name[0])+1);
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- BP := Timeout; { In 1/18th seconds (use only with lock bit set }
- RealModeIntr($21,Regs);
- Result:=AL;
- LogLogicalRecord := (Result=0);
- { FFh fail }
- { FEh timeout }
- { 96h No dynamic memory for file }
- END;
- END;
-
-
- {D1 [1.0+]}
- FUNCTION LockLogicalRecordSet(LockDirective:Byte; TimeoutLimit : Word) : Boolean;
- { Call this to lock all records logged with Log_Logical_Record }
- { LockDirective LD_LOCK = 0; Deny all access to file/record
- LD_LOCK_RO = 1; Allow read / deny write }
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D1;
- AL := LockDirective;
- BP := TimeoutLimit; { In 1/18th seconds, 0 = No wait }
- RealModeIntr($21,Regs);
- Result:=AL;
- LockLogicalRecordSet := (Result=0);
- {00 - Success
- FF - fail,
- FE - timeout }
- END;
- END;
-
- {D2.. [1.0+]}
- FUNCTION ReleaseLogicalRecord(Name : String) : Boolean;
- { Call this to release a logical record lock without removing the rec }
- { from the table }
- Var temp1,temp2:word;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D2;
- UpString(Name);
- Move(Name,GlobalReqBuf^,ord(Name[0])+1);
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- RealModeIntr($21,Regs);
- Result:=AL;
- ReleaseLogicalRecord := (Result=0);
- { FF No record found }
- END;
- END;
-
- {D3.. [1.0+]}
- FUNCTION ReleaseLogicalRecordSet : Boolean;
- { release all locked logical records, doesn't remove them from the table }
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D3;
- RealModeIntr($21,Regs);
- Result:=0;
- ReleaseLogicalRecordSet := True;
- END;
- END;
-
- {D4.. [1.0+]}
- FUNCTION ClearLogicalRecord(Name : String) : Boolean;
- { This call unlocks and removes the Logical Record lock from the table }
- Var temp1,temp2:word;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D4;
- UpString(Name);
- Move(Name,GlobalReqBuf^,ord(Name[0])+1);
- GetGlobalBufferAddress(DS,DX,temp1,temp2);
- { DS:DX real mode pointer to buffer in realmode-range holding Filename }
- RealModeIntr($21,Regs);
- Result:=AL;
- ClearLogicalRecord := (Result=0);
- { FF No record Found }
- END;
- END;
-
- {D5.. [1.0+]}
- FUNCTION ClearLogicalRecordSet : Boolean;
- { Unlocks and removes from the table all of the stations logical record locks }
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $D5;
- RealModeIntr($21,Regs);
- Result:=0;
- ClearLogicalRecordSet := True;
- END;
- END;
-
-
- (************* THE FOLLOWING ARE PHYSICAL RECORD LOCK CALLS ****************)
-
- {F:BC..:Lock (& Log) records in a file}
- function LogPhysicalRecord(Handle:Word;
- LockDirective:Byte;
- RecordOffset,RecordLength:Longint;
- TimeOutLimit:Word): boolean;
- { Max length of name: 99 chars }
- { LockDirective LD_LOG = 0;
- LD_LOG_LOCK = 1; Deny all access to file/record
- LD_LOG_LOCK_RO = 3; Allow read / deny write }
- { TimeOut=0 means NoWait; TimeOut not valid if logging only }
- { Handle is the file handle }
- begin
- with regs
- do begin
- AH := $BC;
- AL := LockDirective;
- BX := Handle;
- CX := HiLong(RecordOffset);
- DX := LowLong(RecordOffset);
- BP := TimeOutLimit;
- SI := HiLong(RecordLength);
- DI := LowLong(RecordLength);
- RealModeIntr($21,Regs);
- Result:=AL;
- LogPhysicalRecord := (Result=0);
- { $FF = fail, $FE Timeout, $96 = No dynamic memory }
- end;
- end;
-
- {BD.. [1.0+]}
- function ReleasePhysicalRecord( Handle:Word; RecordOffset,RecordLength:Longint) : boolean;
- { When a record is released, it is unlocked for use by someone else, but }
- { it remains in the log table }
- { Handle is the file handle, Start_Hi and Start_Lo are the boundaries of }
- { the locked region to be released }
- begin
- with regs
- do begin
- AH := $BD;
- BX := Handle;
- CX := HiLong(RecordOffset);
- DX := LowLong(RecordOffset);
- SI := HiLong(RecordLength);
- DI := LowLong(RecordLength);
- RealModeIntr($21,Regs);
- Result:=AL;
- ReleasePhysicalRecord := (Result=0);
- { $FF = No locked record found}
- end;
- end;
-
- {BE.. [1.0+]}
- function ClearPhysicalRecord(Handle: Word;
- RecordOffset,RecordLength:Longint): boolean;
- { Handle is the file handle, Start_Hi and Start_Lo are the boundaries }
- { of the file region to be locked. Clearing a record will unlock it }
- { and remove it from the log table. }
- begin
- with regs
- do begin
- AH := $BE;
- BX := Handle;
- CX := HiLong(RecordOffset);
- DX := LowLong(RecordOffset);
- SI := HiLong(RecordLength);
- DI := LowLong(RecordLength);
- RealModeIntr($21,Regs);
- Result:=AL;
- ClearPhysicalRecord := (Result=0);
- { $FF No locked record found }
- end;
- end;
-
- {C2.. [1.0+]}
- function LockPhysicalRecordSet(LockDirective: byte; TimeoutLimit: Word): boolean;
- { flgs are the lock flags: bit 1 set means shared (non-exclusive) lock }
- { Timeout is in 1/18 seconds, 0 = no wait, -1 means indefinite wait }
- { This function attempts to lock all of the records logged in the station's }
- { log table. }
- { LockDirective LD_LOCK = 0; Deny all access to file/record
- LD_LOCK_RO = 1; Allow read / deny write }
- { !! There is known problem when the locking directive equals 1. }
- begin
- with regs
- do begin
- AH := $C2;
- AL := LockDirective;
- BP := TimeOutLimit;
- RealModeIntr($21,Regs);
- Result:=AL;
- LockPhysicalRecordSet := (Result=0);
- { $FF = fail, $FE = timeout fail }
- end;
- end;
-
- {C3.. [1.0+]}
- function ReleasePhysicalRecordSet : boolean;
- { unlocks the entire record log table of the station. records remain in }
- { the log table. }
- begin
- regs.AH := $C3;
- RealModeIntr($21,Regs);
- Result:=0;
- ReleasePhysicalRecordSet := True;
- end;
-
- {C4.. [1.0+]}
- function ClearPhysicalRecordSet : boolean;
- { unlocks and removes from the log table any records logged and locked }
- begin
- regs.AH := $C4;
- RealModeIntr($21,Regs);
- Result:=0;
- ClearPhysicalRecordSet := True;
- end;
-
-
- {F217/EF [2.1x+]}
- Function GetLogicalRecordLocksByConnection(ConnNbr:word;
- {i/o} Var NextRecNbr:word;
- Var TaskNbr:word;
- Var LockStatus:Byte;
- Var LockName:String):Boolean;
- { You need console operator rights to use this function }
- Type Treq=record
- len :Word;
- subFunc :Byte;
- _ConnNbr :word; {lo-hi} { !! Invalid numbers may cause an abend }
- _LastRecSeen:word; {lo-hi}
- end;
- Trep=record
- _LastRecSeen :word; {lo-hi}
- _NbrOfRecords:word; {lo-hi}
- _LockInfo :array[1..508] of byte;
- end;
- TPreq=^Treq;
- TPrep=^Trep;
- Begin
- WITH TPreq(GlobalReqBuf)^
- do begin
- subFunc:=$EF;
- _ConnNbr:=ConnNbr;
- _LastRecSeen:=NextRecNbr;
- len:=SizeOf(Treq)-2;
- end;
- F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
- With TPrep(GlobalReplyBuf)^
- do begin
- Move(_LastRecSeen,NextRecNbr,2);
-
-
- end;
- GetLogicalRecordLocksByConnection:=(result=0)
- { Valid completion codes:
- $00 Success
- $FF Failure
- }
- end;
-
- {$IFDEF xxxx}
-
- {F217/ [2.1x+]}
- Function ( ):Boolean;
- Type Treq=record
- len:Word;
- subFunc:Byte;
-
- end;
- Trep=record
-
- end;
- TPreq=^Treq;
- TPrep=^Trep;
- Begin
- WITH TPreq(GlobalReqBuf)^
- do begin
- subFunc:=$
-
- len:=SizeOf(Treq)-2;
- end;
- F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
- With TPrep(GlobalReplyBuf)^
- do begin
-
- end;
- :=(result=0)
- { Valid completion codes:
- $00 Success
- $FF Failure.
- }
- end;
-
- {$ENDIF}
-
- Begin
- SetLockMode(1);
- END.